import log from '../../../helpers/logger';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
//import { validateLink } from '../../../helpers/dataValidation';
import {
  createMinishopOrder,
  editMinishopOrderInDatabase,
  getMinishopOrderFromDatabase,
  queryMinishopOrdersFromDatabase
} from '../../../services/uctoo/minishop_order';
import {
  authorizedRouteHandler,
  ControllerMethodTypes,
  defaultRouteHandler,
} from '../../../../interfaces';
import { Request } from 'hyper-express';
import { showSelectedObjectKeys } from '../../../helpers/utilsJS';
import { wechatpay_transaction } from '../../../../../prisma/generated/uctoo';
import { setExCache } from '../../../helpers/redis';
import { OfficialAccount, ServerRequest, FormData, defineOfficialAccountConfig, Pay, definePayConfig } from 'node-easywechat';
import Message from 'node-easywechat';
import { minishop_order, minishop_order_detail, wechatopen_users } from '../../../../../prisma/generated/uctoo';
import {
  editMinishopOrderDetailInDatabase,
  getMinishopOrderDetailFromDatabase,
} from '../../../services/uctoo/minishop_order_detail';
import {
  editWechatopenUsersInDatabase,
  getWechatopenUsersFromDatabase
} from '../../../services/uctoo/wechatopen_users';
import {
  queryUnipayConfigsFromDatabase
} from '../../../services/uctoo/unipay_config';
import { getUserAccount } from '../../../services/uctoo/user_has_account';
import { getUctooUserFromDatabase } from '../../../services/uctoo/uctoo_user';
import { calculateSkuTotalPrice } from '../../../services/uctoo/minishop_order';
import { webSocketStore, WebSocketMessage } from '../../../websocket/websocket-store';
  //#region AutoCreateCode
import {
  createWechatpayTransaction,
  deleteWechatpayTransactionFromDatabase,
  deleteMultiWechatpayTransactionFromDatabase,
  editWechatpayTransactionInDatabase,
  editMultiWechatpayTransactionInDatabase,
  getWechatpayTransactionFromDatabase,
  getWechatpayTransactionsFromDatabase,
  queryWechatpayTransactionsFromDatabase,
  countWechatpayTransactions
} from '../../../services/uctoo/wechatpay_transaction';

class uctooWechatpayTransactionController {

  protected validateAndDestructureBody = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const body = await req.json();
    const keysArray = Object.keys(body);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooWechatpayTransaction = showSelectedObjectKeys(body, keysArray) as wechatpay_transaction;
    uctooWechatpayTransaction.creator = userId;

    return uctooWechatpayTransaction;
  };
  public add: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const uctooWechatpayTransaction = await this.validateAndDestructureBody(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      if (!uctooWechatpayTransaction) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

      const createdWechatpayTransaction = await createWechatpayTransaction(uctooWechatpayTransaction);
      if (!createdWechatpayTransaction) return res.status(500).json({ errno: "50001", errmsg: "database query failed" });

      res.status(200).json(createdWechatpayTransaction);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public edit: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id,ids,force } = body;

      if(ids){
        const uctooWechatpayTransaction = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooWechatpayTransaction) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedWechatpayTransaction = await editMultiWechatpayTransactionInDatabase(uctooWechatpayTransaction, JSON.parse(ids), user);
        
        if (typeof editedWechatpayTransaction === 'object' && 'success' in editedWechatpayTransaction) {
          if (!editedWechatpayTransaction.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: editedWechatpayTransaction.reason,
              ...(editedWechatpayTransaction.wechatpayTransactionId && { wechatpayTransactionId: editedWechatpayTransaction.wechatpayTransactionId })
            });
          }
          return res.status(200).json(editedWechatpayTransaction.data);
        }
        
        res.status(200).json(editedWechatpayTransaction);
      }else{
        const uctooWechatpayTransaction = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooWechatpayTransaction) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedWechatpayTransaction = await editWechatpayTransactionInDatabase(uctooWechatpayTransaction, uctooWechatpayTransaction.id, user);
        
        if (typeof editedWechatpayTransaction === 'object' && 'success' in editedWechatpayTransaction) {
          if (!editedWechatpayTransaction.success) {
            return res.status(403).json({ errno: "40301", errmsg: editedWechatpayTransaction.reason });
          }
          return res.status(200).json(editedWechatpayTransaction.data);
        }
        res.status(200).json(editedWechatpayTransaction);
      }      
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public delete: authorizedRouteHandler = async (req, res) => {
    try {
      const body = await req.json();
      const { id,ids,force } = body;
      const user = res.locals.id.user;

      if(ids){
        const deletionResult = await deleteMultiWechatpayTransactionFromDatabase(JSON.parse(ids), force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: deletionResult.reason,
              ...(deletionResult.wechatpayTransactionId && { wechatpayTransactionId: deletionResult.wechatpayTransactionId })
            });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }else{
        const deletionResult = await deleteWechatpayTransactionFromDatabase(id, force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({ errno: "40301", errmsg: deletionResult.reason });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }

      res.status(200).json({ desc: '删除成功' });
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getSingle: authorizedRouteHandler = async (req, res) => {
    try {
      const { id } = req.params;
      const user = res.locals.id.user;

      const wechatpayTransactionFromDb = await getWechatpayTransactionFromDatabase(id, user);
      if (!wechatpayTransactionFromDb) {
        return res.status(404).json({ 
          errno: "40401", 
          errmsg: '未找到该实体或您没有权限访问' 
        });
      }

      res.status(200).json(wechatpayTransactionFromDb);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getMany: authorizedRouteHandler = async (req, res) => {
    try {
      const limit = parseInt(req.params.limit);
      const page = parseInt(req.params.page) || 0;
      const skip = parseInt(req.params.skip) || 0;
      const query = req.query;
      
      if (limit > 100) return res.status(400).json({ errno: "40002", errmsg: '请求数量不能超过100条' });
      if (isNaN(limit)) return res.status(400).json({ errno: "40003", errmsg: '请求数量必须是数字' });
      
      const user = res.locals.id.user;
      const totalCount = await countWechatpayTransactions(user);
      
      if (query) {
        const wechatpayTransactionsFromDb = await queryWechatpayTransactionsFromDatabase(limit, page, skip, query, user);
        if (!wechatpayTransactionsFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount: totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          wechatpayTransactions: wechatpayTransactionsFromDb
        });
      } else {
        const wechatpayTransactionsFromDb = await getWechatpayTransactionsFromDatabase(limit, skip, page, user);
        if (!wechatpayTransactionsFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount:totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          wechatpayTransactions: wechatpayTransactionsFromDb
        });
      }


    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  //#endregion AutoCreateCode

  /**
   * @see https://pay.weixin.qq.com/doc/v3/merchant/4012525085
   * @param req 
   * @param actionType 
   * @returns 
   */
  protected validateAndCreateOrder = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const wechatopenUsersFromDb = await getWechatopenUsersFromDatabase(userId) as wechatopen_users;      //order表竟然没有appid，那就用user的appid吧，
    const body = await req.json();
    const param = await req.query_parameters;
    log.info(body);
    const snowId = require('simple-flakeid');
    let gen1 = new snowId.SnowflakeIdv1({ workerId: 1 });
    body['out_order_id'] = gen1.NextId().toString();                                 //雪花算法生成订单唯一id
    body['openid'] = wechatopenUsersFromDb.openid;
    body['appid'] = wechatopenUsersFromDb.appid;
    body['type'] = 0;
    body['platform'] = 'H5';
    body['status'] = 10;
    body['final_price'] = Number(body.final_price);
    let newOrder = {
      out_order_id: gen1.NextId().toString(),
      out_trade_no: gen1.NextId().toString(),
      order_detail_id: '',
      openid: wechatopenUsersFromDb.openid,
      appid: wechatopenUsersFromDb.appid,
      status: 10,
      type: 0,
      platform: 'H5',
      creator: userId,
      final_price: Number(body.final_price)
    };
    const keysArray = Object.keys(newOrder);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooMinishopOrder = showSelectedObjectKeys(newOrder, keysArray) as minishop_order;
    //  log.info(userId);
    log.info(uctooMinishopOrder);
    //  uctooMinishopOrder.creator = userId;

    return uctooMinishopOrder;
  };

  public payTransactionsH5: defaultRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      // 通过订单id取出订单信息
              const id = body.id;
              if (!id) {
                return res.status(400).json({ err: 'isParamValidated', desc: '缺少订单id' });
              }
              let minishopOrderData = await getMinishopOrderFromDatabase(id);
              if (!minishopOrderData) return res.status(400).json({ err: 'isParamValidated', desc: '缺少订单数据' });

      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: body.appid, operator: "wechatpay" });
      const unipayConfigsFromDb = await queryUnipayConfigsFromDatabase(1, 0, 0, params);
      if (!unipayConfigsFromDb) return res.status(404).end();
      log.info(unipayConfigsFromDb[0].value);
      const unipayConfig = JSON.parse(unipayConfigsFromDb[0].value);

      const wechatpayConfig = definePayConfig(unipayConfig)
      const wxapp = new Pay(wechatpayConfig);
      const reqbody = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        reqbody,
        '1.1',
        req.query_parameters
      );
      wxapp.setRequest(request);

      const client = wxapp.getClient();
      //创建订单


      const reqIP = String(req.ip);
      const out_order_id = String(minishopOrderData.out_order_id);

      log.info({ info: 'payTransactionsH5', reqIP: reqIP });
      log.info({ info: 'payTransactionsH5', reqIP: out_order_id });
      const apiUrl = process.env.API_URL;
      const notify_url = `${apiUrl}/api/uctoo/wechatpay_transaction/notify/${body.appid}`

      let orderData = {
        "appid": body.appid,
        "mchid": unipayConfig["mch_id"],
        "description": "支付",
        "out_trade_no": out_order_id,
        "notify_url": notify_url,
        "amount": {
          "total": minishopOrderData.final_price
        },
        "scene_info": {
          "payer_client_ip": reqIP,
          "h5_info": {
            "type": "android"
          }
        }
      }

      const payUrl = (await client.post('/v3/pay/transactions/h5', {
        data: orderData,
      })).toObject();
      log.info('payTransactionsH5');
      payUrl['order_id'] = minishopOrderData.id;
      log.info({ info: 'payTransactionsH5', payUrl: payUrl });

      res.status(200).json(payUrl);

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public payBuyJSAPI: defaultRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      //前端传来的订单数据
      const body = await req.json();
      // 从unipay_config获取支付SDK配置
      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: body.appid, operator: "wechatpay" });
      const unipayConfigsFromDb = await queryUnipayConfigsFromDatabase(1, 0, 0, params);
      if (!unipayConfigsFromDb) return res.status(404).end();
      log.info(unipayConfigsFromDb[0].value);
      const unipayConfig = JSON.parse(unipayConfigsFromDb[0].value);

      const wechatpayConfig = definePayConfig(unipayConfig)
      const wxapp = new Pay(wechatpayConfig);
      const reqbody = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        reqbody,
        '1.1',
        req.query_parameters
      );
      wxapp.setRequest(request);

      const client = wxapp.getClient();
      //创建订单

      const uctooMinishopOrder = await this.validateAndCreateOrder(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      console.log(uctooMinishopOrder);
      if (!uctooMinishopOrder) return res.status(400).json({ err: 'isUserValidated', desc: '提交数据格式错误' });

      const createdMinishopOrder = await createMinishopOrder(uctooMinishopOrder);
      if (!createdMinishopOrder) return res.status(500).end();

      //生成预支付订单号，更新minishop_order.out_trade_no关联。同一订单每次调用预支付，都创建一个新的out_trade_no
      const snowId = require('simple-flakeid');
      let gen1 = new snowId.SnowflakeIdv1({ workerId: 1 });
      const out_trade_no = gen1.NextId().toString();                                 //雪花算法生成预支付订单唯一id
      const reqIP = String(req.ip);
      const out_order_id = String(createdMinishopOrder.out_order_id);

      log.info({ info: 'payTransactionsH5', reqIP: reqIP });
      log.info({ info: 'payTransactionsH5', reqIP: out_order_id });
      const apiUrl = process.env.API_URL;
      const notify_url = `${apiUrl}/api/uctoo/wechatpay_transaction/notify/${body.appid}`

      let orderData = {
        "appid": body.appid,
        "mchid": unipayConfig["mch_id"],
        "description": "支付",
        "out_trade_no": out_trade_no,
        "notify_url": notify_url,
        "amount": {
          "total": createdMinishopOrder.final_price
        },
        "payer": {
          "openid": createdMinishopOrder.openid
        },
        "scene_info": {
          "payer_client_ip": reqIP
        }
      }

      const prepay_id = (await client.post('/v3/pay/transactions/jsapi', {
        data: orderData,
      })).toObject();

      const nowTimestamp = Date.now();
      const date = new Date(nowTimestamp);
      const withTimezone = date.toISOString();

      //更新订单详情minishop_order_detail以及minishop_order    

      /*   const pay_info = {"prepay_id":prepay_id.prepay_id,"transaction_id":"","prepay_time":withTimezone,"pay_time":0,"payment_method":1};
         const price_info = {"product_price":productFinalPrice,"order_price":orderFinalPrice,"freight":freight,"discounted_price":discountedPrice,"is_discounted":false};
         const orderDetail = {
           pay_info: JSON.stringify(pay_info),
           price_info: JSON.stringify(price_info)
         }
         const editedMinishopOrderDetail = await editMinishopOrderDetailInDatabase(orderDetail, order_detail_id);
         if (!editedMinishopOrderDetail) return res.status(500).end();*/
      const order = {
        final_price: createdMinishopOrder.final_price,
        out_trade_no: out_trade_no
      }
      const editedMinishopOrder = await editMinishopOrderInDatabase(order, createdMinishopOrder.id);
      if (!editedMinishopOrder) return res.status(500).end();

      log.info('payBuyJSAPI');
      let sdkConfig = wxapp.getUtils().buildSdkConfig(prepay_id.prepay_id, createdMinishopOrder.appid, "RSA");
      log.info({ info: 'sdkConfig', sdkConfig: sdkConfig });
      sdkConfig['id'] = createdMinishopOrder.id;
      sdkConfig['unipayProvider'] = unipayConfigsFromDb[0].name;
      log.info({ info: 'payTransactionsJSAPI', sdkConfig: sdkConfig });
      res.status(200).json(sdkConfig);

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  /**
   * @see https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/direct-jsons/jsapi-prepay.html
   * @param req 前端传入订单待支付订单数据
   * @param res 
   * @returns 
   */
  public payTransactionsJSAPI: defaultRouteHandler = async (req, res) => {
    try {
      //前端传来的订单数据
      const body = await req.json();
      log.info(body);
      const order_detail_id = body.order_detail_id;
      const id = body.id;
      const openid = body.openid;
      const appid = body.appid;
      const client_id = body.client_id;
      //todo:重构到minishop_order的controllers根据前端用户选择的地址、优惠等信息计算订单最终价格,返回前端显示
      const minishopOrderFromDb = await getMinishopOrderFromDatabase(id) as minishop_order;
      if (!minishopOrderFromDb) return res.status(400).json({ err: 'isParamValidated', desc: '缺少订单数据' });
      log.info({ info: 'minishopOrderFromDb', minishopOrderFromDb: minishopOrderFromDb });
      const minishopOrderDetailFromDb = await getMinishopOrderDetailFromDatabase(order_detail_id) as minishop_order_detail;
      if (!minishopOrderDetailFromDb) return res.status(400).json({ err: 'isParamValidated', desc: '缺少订单详情数据' });
      log.info({ info: 'minishopOrderDetailFromDb', minishopOrderDetailFromDb: minishopOrderDetailFromDb });

             
      //不需要用到用户相关计算的订单，不需要有用户登录态
    //  const user = res.locals.id.user;
    //  if (!user) return res.status(400).json({ err: 'isUserLogined', desc: '提交数据格式错误' });

      // 根据用户类型取出用户信息
    /*  const user_type = body.user_type;
      if (!user_type) return res.status(400).json({ err: 'isUserValidated', desc: '提交数据格式错误' });
      let userInfo = null;
            // 通过用户类型取出用户信息
            if(user_type === 'uctoo_user'){
              const UctooUserFromDb = await getUctooUserFromDatabase(user);
              if (!UctooUserFromDb) return  res.status(400).json({ err: 'isUserLogined', desc: '缺少用户信息' });
              log.info('wechatopenUsersFromDb');
              log.info(UctooUserFromDb);
              //取出uctoo_user关联的user_has_account帐号获取openid
              const userAccount = await getUserAccount(UctooUserFromDb.id);
              log.info('userAccount');
              //用关联帐号的openid补充userInfo
              if (userAccount) {
                UctooUserFromDb['openid'] = userAccount.openid
              }
              log.info(UctooUserFromDb);
              userInfo = UctooUserFromDb;
            }
            if(user_type === 'wechatopen_users'){
              const wechatopenUsersFromDb = await getWechatopenUsersFromDatabase(user);
              if (!wechatopenUsersFromDb) return  res.status(400).json({ err: 'isUserLogined', desc: '缺少用户信息' });
              log.info('wechatopenUsersFromDb');
              log.info(wechatopenUsersFromDb);
              userInfo = wechatopenUsersFromDb;
            }
            log.info('userInfo');
              log.info(userInfo);  

      */      
      if (!appid || !openid) {
        return res.status(400).json({ err: 'isParamValidated', desc: '提交数据格式错误' });
      }
      if (!id) {  //没有id则是跳过支付确认页直接购买的，先生成订单。todo:与payBuyJSAPI接口合并，，，不合并好像也有道理

      }
      // 从unipay_config获取支付SDK配置
      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: body.appid, operator: "wechatpay" });
      const unipayConfigsFromDb = await queryUnipayConfigsFromDatabase(1, 0, 0, params);
      if (!unipayConfigsFromDb) return res.status(404).end();
      log.info(unipayConfigsFromDb[0].value);
      const unipayConfig = JSON.parse(unipayConfigsFromDb[0].value);

      const wechatpayConfig = definePayConfig(unipayConfig)
      const wxapp = new Pay(wechatpayConfig);
      const reqbody = await req.text();

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        reqbody,
        '1.1',
        req.query_parameters
      );
      wxapp.setRequest(request);

      const client = wxapp.getClient();

      //生成预支付订单号，更新minishop_order.out_trade_no关联。同一订单每次调用预支付，都创建一个新的out_trade_no
      const snowId = require('simple-flakeid');
      let gen1 = new snowId.SnowflakeIdv1({ workerId: 1 });
      const out_trade_no = gen1.NextId().toString();                                 //雪花算法生成预支付订单唯一id
      const reqIP = String(req.ip);
      log.info({ info: 'order_detail_id', order_detail_id: order_detail_id });
      
      //计算订单最终支付价格,不信任前端传的值，以服务端数据为准
      //有sku则用sku价格进行计算，没有sku则用minishop_spu.min_price进行计算,todo:此步骤应在创建订单时确保依此生成订单详情数据
      const product_infos = JSON.parse(minishopOrderDetailFromDb.product_infos);
      // 计算sku总价格
              let skuTotalPrice = calculateSkuTotalPrice(product_infos);
              console.log("Total Price:", skuTotalPrice);
              //计算运费价格
      
              //计算优惠
      
              //计算积分抵扣金额
              
              //更新订单数据

      //todo:计算运费
      const freight = 0;

      //todo:计算优惠
      const discountedPrice = 0;

      const orderFinalPrice = skuTotalPrice + freight - discountedPrice;
      log.info({ info: 'orderFinalPrice', orderFinalPrice: orderFinalPrice });
      const apiUrl = process.env.API_URL;
      const notify_url = `${apiUrl}/api/uctoo/wechatpay_transaction/notify/${body.appid}`

      let orderData = {
        "appid": appid,
        "mchid": unipayConfig["mch_id"],
        "description": "支付",
        "out_trade_no": out_trade_no,
        "notify_url": notify_url,
        "amount": {
          "total": orderFinalPrice
        },
        "payer": {
          "openid": openid
        },
        "scene_info": {
          "payer_client_ip": reqIP
        }
      }
      log.info({ info: 'orderData', orderData: orderData });
      const prepay_id = (await client.post('/v3/pay/transactions/jsapi', {
        data: orderData,
      })).toObject();
      log.info('payTransactionsJSAPI');
      const nowTimestamp = Date.now();
      const date = new Date(nowTimestamp);
      const withTimezone = date.toISOString();

      //更新订单详情minishop_order_detail以及minishop_order    

      const pay_info = { "prepay_id": prepay_id.prepay_id, "transaction_id": "", "prepay_time": withTimezone, "pay_time": 0, "payment_method": 1 };
      const price_info = { "product_price": skuTotalPrice, "order_price": orderFinalPrice, "freight": freight, "discounted_price": discountedPrice, "is_discounted": false };
      const orderDetail = {
        pay_info: JSON.stringify(pay_info),
        price_info: JSON.stringify(price_info)
      }
      const editedMinishopOrderDetail = await editMinishopOrderDetailInDatabase(orderDetail, order_detail_id);
      if (!editedMinishopOrderDetail) return res.status(500).end();
      const extJson = JSON.parse(minishopOrderFromDb.ext_json);
      extJson['client_id'] = client_id;
      const order = {
        final_price: orderFinalPrice,
        out_trade_no: out_trade_no,
        ext_json: JSON.stringify(extJson)
      }
      const editedMinishopOrder = await editMinishopOrderInDatabase(order, id);
      if (!editedMinishopOrder) return res.status(500).end();

      let sdkConfig = wxapp.getUtils().buildSdkConfig(prepay_id.prepay_id, appid, "RSA");
      log.info({ info: 'sdkConfig', sdkConfig: sdkConfig });
      sdkConfig['order_id'] = id;
      sdkConfig['unipayProvider'] = unipayConfigsFromDb[0].name;
      sdkConfig['client_id'] = client_id;
      log.info({ info: 'payTransactionsJSAPI', sdkConfig: sdkConfig });
      
      
            
      res.status(200).json(sdkConfig);

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  public notify: defaultRouteHandler = async (req, res) => {

    try {

      const { appid } = req.params;
      log.info({ info: 'transaction.notify.appid', appid });
      let client_id = '';
      // 从unipay_config获取支付SDK配置
      const params: Record<string, any> = {};
      params.filter = JSON.stringify({ appid: appid, operator: "wechatpay" });
      const unipayConfigsFromDb = await queryUnipayConfigsFromDatabase(1, 0, 0, params);
      if (!unipayConfigsFromDb) return res.status(404).end();
      log.info(unipayConfigsFromDb[0].value);
      const unipayConfig = JSON.parse(unipayConfigsFromDb[0].value);

      const wechatpayConfig = definePayConfig(unipayConfig)
      //  log.info('officialAccountServer');
      // log.info(req instanceof http.IncomingMessage);

      const wxapp = new Pay(wechatpayConfig);
      const body = await req.text();
      const bodyJSON = await req.json();
      log.info({ info: 'transaction.notify.body', body });
      log.info({ info: 'transaction.notify.bodyJSON', bodyJSON });

      const request = new ServerRequest(
        req.method,
        req.url,
        req.headers,
        body,
        '1.1',
        req.query_parameters
      );
      wxapp.setRequest(request);

      const client = wxapp.getClient();
      const wxserver = wxapp.getServer();
      wxserver.setRequest(request);

      const dMessage = await wxserver.getDecryptedMessage();
      log.info({ info: 'transaction.notify.dMessage', dMessage });
      const out_trade_no = dMessage.out_trade_no;
      log.info({ info: 'out_trade_no', out_trade_no: out_trade_no });
      //同一支付流水通知多次，先查询避免重复
      const wtparams: Record<string, any> = {};
      wtparams.filter = JSON.stringify({ transaction_id: dMessage.transaction_id });
      const wechatpayTransactionsFromDb = await queryWechatpayTransactionsFromDatabase(1, 0, 0, wtparams);
      log.info({ info: 'wechatpayTransactionsFromDb', wechatpayTransactionsFromDb });
      if (!wechatpayTransactionsFromDb[0]) {
        //创建支付流水数据
        const uctooWechatpayTransaction = {
          notify_id: bodyJSON.id,
          transaction_id: dMessage.transaction_id,//           String    @db.VarChar
          mchid: dMessage.mchid,//                    String    @db.VarChar
          appid: dMessage.appid,             //       String    @db.VarChar
          out_trade_no: dMessage.out_trade_no,         //    String    @db.VarChar
          trade_state: dMessage.trade_state,         //     String    @db.VarChar
          trade_state_desc: dMessage.trade_state_desc,  //       String    @db.VarChar
          bank_type: dMessage.bank_type,        //        String    @db.VarChar
          trade_type: dMessage.trade_type,       //        String    @db.VarChar
          attach: dMessage.attach,         //          String?   @db.VarChar
          success_time: dMessage.success_time,        //     DateTime  @default(now()) @db.Timestamptz(6)
          payer: JSON.stringify(dMessage.payer),          //          String    @db.VarChar
          amount: JSON.stringify(dMessage.amount),         //          String    @db.VarChar
          create_time: bodyJSON.create_time,           //   DateTime  @default(now()) @db.Timestamptz(6)
          scene_info: "",      //         String?   @db.VarChar
          promotion_detail: "", //        String?   @db.VarChar
          is_subscribe: "",      //       String?   @db.VarChar
          resource_type: bodyJSON.resource_type,    //        String?   @db.VarChar
          event_type: bodyJSON.event_type,          //     String?   @db.VarChar
          resource_algorithm: bodyJSON.resource.algorithm,  //     String?   @db.VarChar
          resource_ciphertext: bodyJSON.resource.ciphertext,  //    String?   @db.VarChar
          resource_nonce: bodyJSON.resource.nonce,       //    String?   @db.VarChar
          resource_original_type: bodyJSON.resource.original_type, //  String?   @db.VarChar
          resource_associated_data: bodyJSON.resource.associated_data, //String?   @db.VarChar
          summary: bodyJSON.summary,            //      String?   @db.VarChar
        };
        const createdWechatpayTransaction = await createWechatpayTransaction(uctooWechatpayTransaction);
        log.info({ info: 'createdWechatpayTransaction', createdWechatpayTransaction });
        //查询订单并更新数据
        const moparams: Record<string, any> = {};
        moparams.filter = JSON.stringify({ out_trade_no: dMessage.out_trade_no });
        const minishopOrdersFromDb = await queryMinishopOrdersFromDatabase(1, 0, 0, moparams);
        const minishopOrderDetailFromDb = await getMinishopOrderDetailFromDatabase(minishopOrdersFromDb[0].order_detail_id) as minishop_order_detail;
        const oldPayInfo = JSON.parse(minishopOrderDetailFromDb.pay_info);
        const ext_json = JSON.parse(minishopOrdersFromDb[0].ext_json);
        client_id = ext_json['client_id'];
        const pay_info = { "prepay_id": oldPayInfo.prepay_id, "transaction_id": dMessage.transaction_id, "prepay_time": oldPayInfo.prepay_time, "pay_time": dMessage.success_time, "payment_method": 1 };
        const orderDetail = {
          pay_info: JSON.stringify(pay_info)
        }
        const editedMinishopOrderDetail = await editMinishopOrderDetailInDatabase(orderDetail, minishopOrdersFromDb[0].order_detail_id);
        const order = {
          transaction_id: dMessage.transaction_id,
          status: 20
        }
        const editedMinishopOrder = await editMinishopOrderInDatabase(order, minishopOrdersFromDb[0].id);

      }

      wxserver.with(async function (message) {
        log.info({ info: 'transaction.notify.with', message });

      });

      let Result = { code: "SUCCESS" };

      res.status(200).json(Result);

        //websocket 通知客户端支付结果
        log.info({ info: 'payTransactionsJSAPIclient_id', client_id: client_id });
        const resData = {code:'SUCCESS', message:'支付成功'};
            //websocket 通知客户端登录结果
            // 获取目标客户端连接
            const wsclient = webSocketStore.getClient(client_id);
            if (!client) {
              return 
            }
            const message: WebSocketMessage = {
              type: 'system',
              content: JSON.stringify(resData),
              timestamp: Date.now(),
              clientId: client_id
            }
            wsclient.send(JSON.stringify(message));

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }

  }

  //统计支付流水
  public countTransactions: defaultRouteHandler = async (req, res) => {
    try {
      const totalCount = await countWechatpayTransactions();
      res.status(200).json({
        total: totalCount,
      });

    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }
  };
}

export default uctooWechatpayTransactionController;
